package me.ycy.android.shuffle.synchronizer

import android.app.Service
import android.util.Log
import android.os.{ Bundle, IBinder }
import android.content.Intent
import android.database.Cursor

import java.util.Date

sealed abstract class FieldType[T](x: T) {
  def apply: T = x
  def as[T1]: T1 = x.asInstanceOf[T1]
  def klass: Class[T]
}

case class BlobT(x: Array[Byte]) extends FieldType[Array[Byte]](x) {
  def klass = classOf[Array[Byte]]
}

case class LongT(x: Long) extends FieldType[Long](x) {
  def klass = classOf[Long]
}

case class IntT(x: Int) extends FieldType[Int](x) {
  def klass = classOf[Int]
}

case class ShortT(x: Short) extends FieldType[Short](x) {
  def klass = classOf[Short]
}

case class StringT(x: String) extends FieldType[String](x) {
  def klass = classOf[String]
}

case class FloatT(x: Float) extends FieldType[Float](x) {
  def klass = classOf[Float]
}

case class DoubleT(x: Double) extends FieldType[Double](x) {
  def klass = classOf[Double]
}

case class BooleanT(x: Boolean) extends  FieldType[Boolean](x) {
  def klass = classOf[Boolean]
}

case class DateT(x: Date) extends FieldType[Date](x) {
  def klass = classOf[Date]
}

object Helper {
  def cursorExtract(c: Cursor, p: Array[String],
                    t: List[Class[_]]): Map[String, FieldType[_]] = {
    val blobFunc = (c: Cursor, i: Int) => BlobT(c.getBlob(i))

    val map: Map[Class[_], ((Cursor, Int) => FieldType[_])] = Map(
      classOf[Array[Byte]] -> blobFunc,
      classOf[Long]        -> ((x, y) => LongT(x.getLong(y))),
      classOf[Int]         -> ((x, y) => IntT(x.getInt(y))),
      classOf[Short]       -> ((x, y) => ShortT(x.getShort(y))),
      classOf[String]      -> ((x, y) => StringT(x.getString(y))),
      classOf[Float]       -> ((x, y) => FloatT(x.getFloat(y))),
      classOf[Double]      -> ((x, y) => DoubleT(x.getDouble(y))),
      classOf[Boolean]     -> ((x, y) => BooleanT(x.getInt(y) != 0)),
      classOf[Date]        -> ((x, y) => DateT(new Date(x.getLong(y))))
    )

    var ret: Map[String, FieldType[_]] = Map()
    val n = List(p.size, t.size).min
    for (i <- 0 until n) {
      val v = map.getOrElse(t(i), blobFunc)(c, i)
      ret += p(i) -> v
    }
    ret
  }

  def withCursor[T](c: Cursor)(f: Cursor => T): T = {
    val ret = f(c)
    c.close
    ret
  }
}


trait Logging extends Service {
  val Tag: String
  abstract override def onCreate = {
    Log.d(Tag, "service onCreate")
    super.onCreate
  }

  abstract override def onStartCommand(i: Intent, flags: Int, startId: Int): Int = {
    Log.d(Tag, "service onStartCommand")
    super.onStartCommand(i, flags, startId)
  }

  abstract override def onDestroy: Unit = {
    Log.d(Tag, "service onDestroy")
    super.onDestroy
  }

  abstract override def onLowMemory: Unit = {
    Log.d(Tag, "service onLowMemory")
    super.onLowMemory
  }

  abstract override def onBind(intent: Intent): IBinder = {
    Log.d(Tag, "service onBind")
    super.onBind(intent)
  }
}
